/* Copyright 2010 Speech and Language Technologies Lab, The Ohio State University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package edu.osu.slate.relatedness.swwr.setup.category;

import java.io.*;
import java.util.*;

import edu.osu.slate.relatedness.Configuration;
import edu.osu.slate.relatedness.swwr.data.category.CategoryIDGraph;
import edu.osu.slate.relatedness.swwr.data.category.CategoryIDNode;

/**
 * Program to create the category tree.
 * 
 * <ul>
 *   <li> Preceded by {@link CreateCategoryList} </li>
 *   <li> Followed by {@link CreateInboundEdgeCounts} </li>
 * </ul>
 * 
 * @author weale
 */
public class CheckCategoryGraph {

  /* Name of the input file generated by Wiki (page.sql) */
  private static String inputFileName, outputFileName;

  private static CategoryIDGraph cg;
  
  /**
   * Runs the program.
   * 
   * @param args Name of the configuration file (if needed)
   * @throws ClassNotFoundException 
   */
  public static void main(String[] args) throws ClassNotFoundException
  {
    //Read Configuration File
    if(args.length == 1)
    {
      Configuration.parseConfigurationFile(args[0]);
    }
    else
    {
      Configuration.parseConfigurationFile("/scratch/weale/data/config/enwiktionary/CreateMappings.xml");
    }
    
    /* Set file names */
    inputFileName = Configuration.baseDir + "/" +
                    Configuration.binaryDir + "/" +
                    Configuration.type + "/" +
                    Configuration.date + "/" +
                    Configuration.type + "-" + Configuration.date +
                    "-" + Configuration.graph + ".cgraph";


    //Reading  Initial .cgraph file
    System.out.println("Reading .cgraph file.");
    try
    {
      ObjectInputStream in = new ObjectInputStream(new FileInputStream(inputFileName));
      cg = (CategoryIDGraph) in.readObject();
      in.close();
    }//end: try {}
    catch(IOException e)
    {
      System.out.println("Problem reading file: " + inputFileName);
      System.exit(1);
    }//end: catch(IOException)
    
    System.out.println("Removing Cycles");
    cg.removeCycles();
    
    System.out.println("Writing .agraph file.");
    outputFileName = Configuration.baseDir + "/" +
                     Configuration.binaryDir + "/" +
                     Configuration.type + "/" +
                     Configuration.date + "/" +
                     Configuration.type + "-" + Configuration.date +
                     "-" + Configuration.graph + ".agraph";
    try
    {
      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(outputFileName));
      out.writeObject(cg);
      out.close();
    }//end: try {}
    catch(IOException e)
    {
      System.out.println("Problem reading file: " + inputFileName);
      System.exit(1);
    }//end: catch(IOException)
  }//end: main()
  
  private static boolean checkForLoop(CategoryIDNode cin, int[] parents)
  {
    int[] children = cin.getChildrenIDs();
    
    // Base Cases
    if(children == null)
    { // No Children
      return false;
    }
    else if(Arrays.binarySearch(parents, cin.getCategoryID()) >= 0)
    { // Loop Found
      System.out.println("Cycle Found: " + cin.getCategoryID());
      return true;
    }
    
    // Set up new parent array
    int[] newParents = new int[parents.length+1];
    System.arraycopy(parents, 0, newParents, 0, parents.length);
    newParents[parents.length] = cin.getCategoryID();
    Arrays.sort(newParents);
    
    boolean stop = false;
    for(int i = 0; !stop && i < children.length; i++)
    {
      stop = checkForLoop(cg.getMember(children[i]), newParents);
    }//end: for(i)
    return stop;
  }
  

}
